use bat::line_range::{LineRange, LineRanges};
use std::fs;

pub fn preview_code(file_path: &str, line_number: usize, end_line: usize) -> Result<(), String> {
    preview_code_with_fallback(file_path, line_number, Some(end_line))
}

pub fn preview_code_with_fallback(
    file_path: &str,
    line_number: usize,
    end_line: Option<usize>,
) -> Result<(), String> {
    // Read file content
    let content = fs::read_to_string(file_path).map_err(|e| e.to_string())?;

    // Calculate starting line (show 3 lines before the code block)
    let start_line = line_number.saturating_sub(3).max(1);

    // Determine end line
    let end_line = if let Some(provided_end) = end_line {
        provided_end
    } else {
        // Fallback: find the code block end by parsing the file
        let lines: Vec<&str> = content.lines().collect();
        let mut code_block_end = line_number;

        if line_number <= lines.len() {
            let mut in_code_block = false;
            for (idx, line) in lines.iter().enumerate().skip(line_number - 1) {
                if !in_code_block && line.trim().starts_with("```") {
                    in_code_block = true;
                } else if in_code_block && line.trim().starts_with("```") {
                    code_block_end = idx + 1;
                    break;
                }
            }

            // If we didn't find the end, use a reasonable default
            if code_block_end == line_number {
                code_block_end = (line_number + 20).min(lines.len());
            }
        }
        code_block_end
    };

    // Create LineRange and build LineRanges
    let line_range = LineRange::new(start_line, end_line);
    let line_ranges = LineRanges::from(vec![line_range]);

    // Use bat::PrettyPrinter to display preview content, using line_ranges to limit line range
    bat::PrettyPrinter::new()
        .input_file(file_path)
        .line_numbers(true)
        .header(false)
        .highlight(line_number) // Highlight the code block start line
        .line_ranges(line_ranges)
        .grid(false)
        .language("markdown")
        .print()
        .map_err(|e| e.to_string())?;

    Ok(())
}
